﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TheLoader.classes
{

    public class TestRunEventArgs
    {
        internal bool _IsRunning = false;
        internal TheLoaderTest _CurrentTest;
        internal DateTime _StartTime;
        internal DateTime _EndTime;
        internal TimeSpan _Duration;
        internal string _URL;
        internal int _ThreadsRunning;
        

        public DateTime StartTime { get { return _StartTime; } }
        public DateTime EndTime { get { return _EndTime; } }
        public TimeSpan Duration { get { return _Duration; } }
        public int ThreadsRunning { get { return _ThreadsRunning; } }
        public string URL { get { return _URL; } }
       
        public TheLoaderTest CurrentTest
        {
            get { return _CurrentTest; }
        }

    }

    public class TestRun
    {

        public delegate void TestRunStartEventHandler(TestRunEventArgs e);
        public delegate void TestRunEndEventHandler(TestRunEventArgs e);
        public delegate void TestStartEventHandler(TestRunEventArgs e);
        public delegate void TestEndEventHandler(TestRunEventArgs e);
        public delegate void TestRunStatusUpdateHandler(TestRunEventArgs trArgs, TheLoaderTestEventArgs tArgs);

        public event TestRunStartEventHandler TestRunStarted;
        public event TestRunEndEventHandler TestRunEnded;
        public event TestStartEventHandler TestStarted;
        public event TestEndEventHandler TestEnded;
        public event TestRunStatusUpdateHandler StatusUpdated;

        public Collection<TheLoaderTest> TestsCollection = new Collection<TheLoaderTest>();
        public bool IsRunning { get; set; }
        public int NumberOfRuns { get; set; }
        public int NumberOfUsers { get; set; }
       
        public List<string> URLs = new List<string>();
        
        public Collection<BackGroundBrowser> bgbs = new Collection<BackGroundBrowser>();
        public Collection<Thread> bgws = new Collection<Thread>();
        public int threadsRunning = 0;
        TestRunEventArgs tre = new TestRunEventArgs();
        public int TotalUrls = 0;
        public double TotalSeconds = 0.0d;
        
        public TheLoaderResults results;


        private void StartThreads()
        {
            foreach (BackGroundBrowser b1 in bgbs)
            {
                                
                Thread t = new Thread(new ThreadStart(b1.StartRun));
                bgws.Add(t);
                threadsRunning++;
                tre._ThreadsRunning = threadsRunning;
            }
        }

        public void Start()
        {
            tre._StartTime = DateTime.Now;
            tre._IsRunning = true;
            IsRunning = true;
            results.StartTime = DateTime.Now;
            StartThreads();
            Parallel.For(0, bgws.Count, i =>
            {
                
                StartThread(bgws, i);
            });
            if (this.TestRunStarted != null)
                TestRunStarted(tre);
        }

        private static void StartThread(Collection<Thread> threads, int num)
        {
            threads[num].Start();
        }

        public void Stop()
        {
            for (int i = 0; i < bgws.Count; i++)
            {
                
                bgws[i].Abort();
                while (bgws[i].IsAlive)
                {
                    string s = bgws[i].IsAlive.ToString();
                }
                
                bgws[i] = null;
                threadsRunning--;
                tre._ThreadsRunning = threadsRunning;
                if (tre._ThreadsRunning <= 0)
                {
                    tre._ThreadsRunning = 0;
                   
                }
                
               
            }
            bgws.Clear();
            bgbs.Clear();
            bgws = new Collection<Thread>();
            bgbs = new Collection<BackGroundBrowser>();
            tre._IsRunning = false;
            this.IsRunning = false;
            if (this.TestRunEnded != null)
                TestRunEnded(tre);
    }

        public void CreateObjects()
        {

           this.results = new TheLoaderResults();
           this.results.TestsCollection = new Collection<TheLoaderTest>();
           this.results.URLCollection = new Collection<string>();
           this.results.NumberOfTests = NumberOfRuns;
           this.results.NumberOfUsers = NumberOfUsers;
            foreach (string s in URLs)
            {
                results.URLCollection.Add(s);
            }

            for (int i = 0; i < NumberOfUsers; i++)
            {
                BackGroundBrowser bgb = new BackGroundBrowser();
                TheLoaderTest test = new TheLoaderTest();
                test.TestStarted += new TheLoaderTest.TestStartEventHandler(bgb_TestStarted);
                test.TestEnded += new TheLoaderTest.TestEndEventHandler(bgb_TestEnded);
                bgb.NumberOfTests = NumberOfRuns;

                test.BrowseEnded += new TheLoaderTest.BrowseEndEventHandler(bgb_BrowseEnded);
                test.TestID = "Test " + i;
                foreach (string s in URLs)
                {
                    test.URLs.Add(s);
                }

                results.TestsCollection.Add(test);
                this.TestsCollection.Add(test);
                bgb.currentTest = test;
                bgbs.Add(bgb);

            }
        }

        #region Background Browser

        protected void bgb_TestStarted(TheLoaderTestEventArgs e)
        {
            
          
                   tre._CurrentTest = e.CurrentTest;
                   
               
            if (this.StatusUpdated != null)
                StatusUpdated(tre, e);
        }

        protected void bgb_TestEnded(TheLoaderTestEventArgs e)
        {
            tre._CurrentTest = e.CurrentTest;
            
            if (this.StatusUpdated != null)
                StatusUpdated(tre, e);
        }

        protected void bgb_BrowseStarted(TheLoaderTestEventArgs e)
        {

            tre._CurrentTest = e.CurrentTest;
            if (this.StatusUpdated != null)
                StatusUpdated(tre, e);

        }

        protected void bgb_BrowseEnded(TheLoaderTestEventArgs e)
        {

            tre._CurrentTest = e.CurrentTest;
            if (this.StatusUpdated != null)
                StatusUpdated(tre, e);
        }

        #endregion
  }
    
}
